/*
 * @(#)InnerClassBuilder.java 1.0 2009/12/01
 */
package stardust.core.java.compiler;


import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.ToolProvider;
import stardust.core.io.IOUtils;
import stardust.core.java.SystemError;


/**
 * <code>InnerClassBuilder</code> 类利用虚拟机内部编译器编译源程序。
 * <p/>
 * @see JavacClassBuilder
 * @see AbstractClassBuilder
 * @see ClassBuilderFactory
 * @version 1.0, 2009/12/01
 * @author ChenChang
 */
public class InnerClassBuilder extends AbstractClassBuilder
{

  /**
   * 系统编译器。
   */
  private JavaCompiler javac;

  /**
   * Java 源程序文件管理器。
   */
  private JavaFileManager fileManager;

  /**
   * 创建一个单例的 <tt>ClassBuilder</tt> 值。
   */
  public InnerClassBuilder()
  {
    this(IOUtils.getTemporarilyDirectory());
  }

  /**
   * 通过限定的目录创造一个 <tt>ClassBuilder</tt> 值。
   * <p/>
   * @param targetDirectory
   * 目标生成目录。
   */
  public InnerClassBuilder(File targetDirectory)
  {
    super(targetDirectory);

    javac = ToolProvider.getSystemJavaCompiler();

    if (javac == null)
    {
      try
      {
        throw new SystemError("无法获取系统 Java 编译器。");
      }
      catch(SystemError e)
      {
        log.error(e, "获取系统 Java 编译器失败，无法进行编译操作，ToolProvider.getSystemJavaCompiler() 返回 null 值。");

        throw e;
      }
    }

    fileManager = javac.getStandardFileManager(null, null, null);
  }

  /**
   * 执行编译动作。
   * <p/>
   * @return 编译成功标志。
   */
  public boolean compile()
  {
    List<VirtualClassFileObject> vfiles = new ArrayList<VirtualClassFileObject>();
    Iterator<String> names = super.files.keySet().iterator();
    String name;

    while (names.hasNext() && (name = names.next()) != null)
    {
      vfiles.add(new VirtualClassFileObject(name, super.files.get(name)));
    }

    CompilationTask task = javac.getTask(new PrintWriter(System.out), fileManager, null, this.args, null, vfiles);

    if (task.call())
    {
      log.trace("编译代码：", super.files);

      return true;
    }
    else
    {
      this.log.warning("无法编译代码：", super.files);

      return false;
    }
  }

}
